package ui.component;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import ui.converter.AttributeConverter;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import model.Attribute;
import model.Database;
import model.Table;
import mongodb.MongoDb;
import ui.DatabaseHandler;

/**
 *
 * @author Merli András-Bertalan
 */
public class IndexView extends VBox {

    private Attribute selectedAttribute;
    private int selectedAttributeIndex;
    private Attribute primaryAttribute;
    private int primaryAttributeIndex;

    public void updateUi(final Database selectedDatabase, final Table selectedTable, final DatabaseHandler databaseHandler) {
        getChildren().clear();

        final Label titleLabel = new Label("Edit Table Indexes");

        titleLabel.setFont(
                new Font("Arial", 20));


        final List<Attribute> attributes = selectedTable.getAttributes();
        for (int index = 0; index < attributes.size(); index++) {
            if (attributes.get(index).getIsPrimary()) {
                primaryAttribute = attributes.get(index);
                primaryAttributeIndex = index;
                break;
            }
        }

        List<Attribute> attributesForComboBox = new ArrayList<>(attributes);
        attributesForComboBox.remove(primaryAttribute);
        selectedAttribute = attributesForComboBox.get(0);
        selectedAttributeIndex = attributes.indexOf(selectedAttribute);

        HBox indexBox = new HBox();
        final ContentView contentView = new ContentView();
        ComboBox<Attribute> attributeComboBox = new ComboBox<>(FXCollections.observableArrayList(attributesForComboBox));
        attributeComboBox.setConverter(new AttributeConverter());
        attributeComboBox.setPromptText("Index: ");

        final Button createIndexButton = new Button("Create Index");
        final Button removeIndexButton = new Button("Remove Index");
        createIndexButton.setDisable(true);
        removeIndexButton.setDisable(true);
        createIndexButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                selectedAttribute.setIsIndexed(true);

                Attribute keyAttribute = new Attribute("key", "String", true, true);
                Attribute valueAttribute = new Attribute("value", "String", false, false);
                Table indexTable = new Table(selectedTable.getName() + "_" + selectedAttribute.getName(), Arrays.asList(keyAttribute, valueAttribute));

                List<List<String>> indexTableValues = new ArrayList<>();
                List<List<String>> tableValues = selectedTable.getValues();
                List<String> parsedKeys = new LinkedList<>();
                for (int i = 0; i < tableValues.size(); i++) {
                    List<String> item = tableValues.get(i);
                    String value = item.get(primaryAttributeIndex);
                    String key = item.get(selectedAttributeIndex);

                    if (!parsedKeys.contains(key)) {
                        for (int j = i + 1; j < tableValues.size(); j++) {
                            if (tableValues.get(j).get(selectedAttributeIndex).equals(key)) {
                                value = value + " " + tableValues.get(j).get(primaryAttributeIndex);
                            }
                        }
                        parsedKeys.add(key);
                        indexTableValues.add(Arrays.asList(key, value));
                    }
                }

                indexTable.setValues(indexTableValues);
                selectedDatabase.addIndexTable(indexTable);
                
                try {
                    MongoDb.createIndex(selectedDatabase, indexTable, keyAttribute);
                } catch (UnknownHostException ex) {
                    Logger.getLogger(IndexView.class.getName()).log(Level.SEVERE, null, ex);
                }
                
                createIndexButton.setDisable(true);
                removeIndexButton.setDisable(false);
                contentView.updateUi(selectedDatabase, indexTable, null, databaseHandler);
                contentView.hideAddAndDeleteButton();
                contentView.setVisible(true);
            }
        });
        removeIndexButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                selectedAttribute.setIsIndexed(false);
                Table indexTable = databaseHandler.getIndexTableByDatabaseAndTableName(selectedDatabase, selectedTable.getName() + "_" + selectedAttribute.getName());
                selectedDatabase.deleteIndexTable(indexTable);
                try {
                    MongoDb.dropIndex(selectedDatabase, indexTable, new Attribute("key", null, true, true));
                } catch (UnknownHostException ex) {
                    Logger.getLogger(IndexView.class.getName()).log(Level.SEVERE, null, ex);
                }
                createIndexButton.setDisable(false);
                removeIndexButton.setDisable(true);
                contentView.setVisible(false);
            }
        });

        attributeComboBox.valueProperty().addListener(new ChangeListener<Attribute>() {
            @Override
            public void changed(ObservableValue<? extends Attribute> ov, Attribute t, Attribute t1) {
                selectedAttribute = t1;
                selectedAttributeIndex = attributes.indexOf(selectedAttribute);

                if (selectedAttribute.getIsIndexed()) {
                    createIndexButton.setDisable(true);
                    removeIndexButton.setDisable(false);
                    Table indexTable = databaseHandler.getIndexTableByDatabaseAndTableName(selectedDatabase, selectedTable.getName() + "_" + selectedAttribute.getName());
                    contentView.updateUi(selectedDatabase, indexTable, null, databaseHandler);
                    contentView.hideAddAndDeleteButton();
                    contentView.setVisible(true);
                } else {
                    createIndexButton.setDisable(false);
                    removeIndexButton.setDisable(true);
                    contentView.setVisible(false);
                }
            }
        });

        indexBox.getChildren().addAll(attributeComboBox, createIndexButton, removeIndexButton);

        setSpacing(
                5);
        setPadding(
                new Insets(10, 0, 0, 10));
        getChildren()
                .addAll(titleLabel, indexBox, contentView);
    }
}
